using GameKit.Core;
using GameKitUnity.Core.Context;
using OneGame.Gameplay.Core;
using UnityEngine;
using UnityEngine.AI;
using UnityHFSM;

namespace OneGame.Gameplay.Monster
{
    public static class MonsterStates
    {
        public const string Idle = "Idle";
        public const string Move = "Move";
        public const string Chase = "Chase";
        public const string Attack = "Attack";
        public const string Dead = "Dead";
    }

    public class MonsterController : MonoBehaviour, IActor
    {
        [SerializeField]
        private float attackDistance = 1.5f;

        [SerializeField]
        private float chaseDistance = 2f;

        [SerializeField]
        private float updateDestinationInterval = .1f;

        private static readonly int DeadHash = Animator.StringToHash("Dead");
        private static readonly int SpeedHash = Animator.StringToHash("Speed");
        private static readonly int AttackHash = Animator.StringToHash("Attack");
        private StateMachine _stateMachine;
        private Animator _animator;
        private StateController _stateController;
        private NavMeshAgent _navMeshAgent;
        private float _timer;

        // PUBLIC
        public IActorModel Model { get; set; } = new ActorModel();
        public Transform TargetTransform;

        private void Awake()
        {
            _animator = GetComponent<Animator>();
            _navMeshAgent = GetComponent<NavMeshAgent>();
            // _navMeshAgent.stoppingDistance = chaseStoppingDistance; // 不管用啊
        }

        public void Start()
        {
            // TODO 读取配置
            SetAttribute(CombatAttributeKeys.Health, 100);

            // 状态机
            _stateMachine = new StateMachine();
            _stateMachine.AddState(MonsterStates.Idle, onEnter: _ => { Log.Info("Enter Idle"); });
            _stateMachine.AddState(MonsterStates.Chase,
                onEnter: _ =>
                {
                    _timer = 0;
                    _navMeshAgent.isStopped = false;
                    _animator.SetFloat(SpeedHash, _navMeshAgent.speed);
                },
                onLogic: s =>
                {
                    var playerPosition = TargetTransform.position;
                    _timer += s.timer.Elapsed;
                    if (_timer > updateDestinationInterval)
                    {
                        _navMeshAgent.destination = playerPosition;
                        _timer = 0;
                    }

                    // unity中两个gameObject位置重叠但存在高度差，如果其中一个transform.LookAt另一个的transform.position会出现奇怪的角度
                    // transform.LookAt(new Vector3(playerPosition.x, 0, playerPosition.z));
                    var direction = playerPosition - transform.position;
                    direction.y = 0; // 忽略高度差
                    if (direction != Vector3.zero)
                    {
                        transform.rotation = Quaternion.LookRotation(direction);
                    }
                },
                onExit: _ =>
                {
                    _navMeshAgent.destination = transform.position; // 停下来
                    _animator.SetFloat(SpeedHash, 0); // TODO 平滑动作
                    _navMeshAgent.isStopped = true;
                }
            );
            _stateMachine.AddState(MonsterStates.Dead, onEnter: _ =>
            {
                Log.Info("Enter Dead");
                _animator.SetTrigger(DeadHash);
                _stateController.Hide();
            });
            _stateMachine.AddState(MonsterStates.Attack,
                onEnter: _ =>
                {
                    // 攻击状态是瞬间切过来，注意动作上是否有Exit Time
                    _animator.SetInteger(AttackHash, 1);
                },
                onLogic: _ =>
                {
                    // TODO 攻击逻辑
                },
                onExit: _ => { _animator.SetInteger(AttackHash, 0); }
            );
            // _stateMachine.SetStartState(MonsterStates.Idle);
            _stateMachine.SetStartState(MonsterStates.Chase);
            _stateMachine.AddTransition(MonsterStates.Idle, MonsterStates.Dead, _ => Model.IsDead);
            _stateMachine.AddTransition(MonsterStates.Chase, MonsterStates.Attack, _ => Vector3.Distance(transform.position, TargetTransform.position) < attackDistance);
            _stateMachine.AddTransition(MonsterStates.Attack, MonsterStates.Chase, _ => Vector3.Distance(transform.position, TargetTransform.position) > chaseDistance);
            _stateMachine.AddTransitionFromAny(MonsterStates.Dead, _ => IsDead);
            _stateMachine.Init();
            _stateMachine.StateChanged += OnStateChanged;
            // 头顶的状态
            _stateController = this.AddSystem(new StateController(GetComponent<IStateView>()));
            _stateController.Init(Model.GetAttribute(CombatAttributeKeys.Health));
        }

        private static void OnStateChanged(StateBase<string> state)
        {
            Log.Info("Monster state changed", state.name);
        }

        public void Update()
        {
            _stateMachine.OnLogic();
        }

        public void TakeDamage(int damage)
        {
            var health = Model.GetAttribute(CombatAttributeKeys.Health) - damage;
            SetAttribute(CombatAttributeKeys.Health, health);
            _stateController.TakeDamage(damage);
        }

        private void SetAttribute(CombatAttributeKeys attribute, int value)
        {
            Model.SetAttribute(attribute, value);

            if (attribute == CombatAttributeKeys.Health && value <= 0)
            {
                Model.State |= ActorState.Dead;
            }
        }

        private bool IsDead => (Model.State & ActorState.Dead) != 0;
    }
}